package cn.bbstone.pisces2.client;

import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.bbstone.pisces2.client.executor.ClientExecutor;
import cn.bbstone.pisces2.client.executor.ClientExecutorPool;
import cn.bbstone.pisces2.client.util.MsgUtil;
import cn.bbstone.pisces2.comm.Const;
import cn.bbstone.pisces2.comm.cache.ClientFliIndexCache;
import cn.bbstone.pisces2.comm.fli.FliSavePoint;
import cn.bbstone.pisces2.config.ConfigFactory;
import cn.bbstone.pisces2.config.ConfigModel;
import cn.bbstone.pisces2.listener.BaseListenerRegister;
import cn.bbstone.pisces2.listener.IListenerRegister;
import cn.bbstone.pisces2.listener.OpEnum;
import cn.bbstone.pisces2.listener.OpUtil;
import cn.bbstone.pisces2.util.CtxUtil;
import cn.bbstone.pisces2.util.FLIUtil;

/**
 * FileTask default SBUF_SIZE min 4M, if there are 10 client, min require memory
 * 4M x 10 = 40M SBUF_SIZE set 32M, min require memory 32M x 10 = 320M
 *
 */
public class ClientStarter {
	private static Logger log = LoggerFactory.getLogger(ClientStarter.class);
	
	private static ConcurrentHashMap<String, FileClient> clientMaps = new ConcurrentHashMap<>();

	public static void main(String[] args) {
		startup(null, null);
	}

	public static void startup(ConfigModel configModel, IListenerRegister listenerRegister) {
		long maxMem = Runtime.getRuntime().maxMemory() / (1024 * 1024);
		if (maxMem < 64) { // 64MB
			throw new RuntimeException("run one client require memory minimal 64 MB.");
		}
		// init configs
		if (configModel == null) {
			configModel = ConfigFactory.loadConfigs(Const.CLIENT);
		}
		CtxUtil.setConfigModel(configModel);
		// register OpListners
		BaseListenerRegister.init(listenerRegister);
		// reset key status
		resetStatus();
		// start clients
		for (int i = 0; i < CtxUtil.getConfigModel().getConnNum(); i++) {
			ClientExecutor clientExecutor = new ClientExecutor();
			ClientExecutorPool.submit(clientExecutor);
		}
		
		OpUtil.execListener(OpEnum.s4_done_startup_client);
		log.info("client is running...");
//        FileClient client = new FileClient();
//        client.startup();
	}

	public static void shutdown() {
		if (clientMaps.size() == 0)
			return;
		Collection<FileClient> fileClients = clientMaps.values();
		for (FileClient client : fileClients) {
			client.shutdown();
		}
	}

	public static void addClient(String uuid, FileClient fileClient) {
		clientMaps.put(uuid, fileClient);
	}
	
	private static boolean resetStatus() {
		boolean bool = false;
		// reset cache current pos
		ClientFliIndexCache.resetCurrentPos();
		// reset save point count, run with NEW mode fliSavePointDisk will be null
		FliSavePoint fliSavePointDisk = FLIUtil.readClientSavePoint();
		if (fliSavePointDisk != null) {
			fliSavePointDisk.setFileNo(-1L);
			fliSavePointDisk.setUpdateTime(System.currentTimeMillis());
			FLIUtil.writeClientSavePoint(fliSavePointDisk);
		}
		// reset initial status
        MsgUtil.resetInitialStatus();
		return bool;
	}
	

}
